/*************************************************************
*
* DS_BIT_ARRAY.CPP
*
*************************************************************/
#include "ap\ap_comm.h"
#include "ds_bit_array.h"
#include "ds_comm.h"
#include "ds_algorithm.h"


/*************************************************************
* dsBIT_ARRAY::SetYesMask ()
*************************************************************/
void dsBIT_ARRAY_IMPL::SetYesMask (int i, DWORD mask, DWORD* array, int nElem) 
{
   int   ind, shift;

   ind   = Bit2Idx(i);
   shift = Bit2Shift(i);

   if (shift == 0) {
      _SetStateYes(array[ind],   mask);
   } else {
      _SetStateYes(array[ind],   mask << shift);
      _SetStateYes(array[ind+1], mask >> (DS_BA_BPW-shift));
   }
   return;
}

/*************************************************************
* dsBIT_ARRAY::SetNoMask ()
*************************************************************/
void dsBIT_ARRAY_IMPL::SetNoMask (int i, DWORD mask, DWORD* array, int nElem) 
{
   int   ind, shift;

   ind   = Bit2Idx(i);
   shift = Bit2Shift(i);

   if (shift == 0) {
      _SetStateNo(array[ind],   mask);
   } else {
      _SetStateNo(array[ind], mask << shift);
      _SetStateNo(array[ind+1], mask >> (DS_BA_BPW-shift));
   }
   return;
}
/*************************************************************
* dsBIT_ARRAY::IsMask ()
*************************************************************/
BOOL dsBIT_ARRAY_IMPL::IsMask (int i, DWORD mask, DWORD const* array, int nElem) 
{
   int   ind, shift;

   ind   = Bit2Idx(i);
   shift = Bit2Shift(i);
   if (shift == 0) {
      return _IsState(array[ind], mask);
   }
   return _IsState(array[ind], mask << shift) || _IsState(array[ind+1], mask >> (DS_BA_BPW-shift));
}

dsBIT_ARRAY::dsBIT_ARRAY (int size, apCL cl)
	: nElem(), array()
#ifndef _RETAIL
	, __cl(cl)
#endif
{
	Resize(size);
}

/**************************************************************************
* dsBIT_ARRAY::Swap()                                                     *
*                                                                         *
**************************************************************************/
void dsBIT_ARRAY::Swap(dsBIT_ARRAY & p)
{
	dsSwap(nElem, p.nElem);
	dsSwap(array, p.array);
}

/*************************************************************
* dsBIT_ARRAY::dsBIT_ARRAY ()
*
*************************************************************/
dsBIT_ARRAY::dsBIT_ARRAY (apCL cl) : nElem(0), array(NULL) 
#ifndef _RETAIL
, __cl(cl)
#endif
{
}

/*************************************************************
* dsBIT_ARRAY::~dsBIT_ARRAY ()
*
*************************************************************/
dsBIT_ARRAY::~dsBIT_ARRAY (void)
{
   if (array) {
      Term();
   }
}

/*************************************************************
* dsBIT_ARRAY::dsBIT_ARRAY ()
*
*************************************************************/
dsBIT_ARRAY::dsBIT_ARRAY(const dsBIT_ARRAY &src, apCL cl) : nElem(0), array(NULL)
#ifndef _RETAIL
, __cl(cl)
#endif
{
   Init(src.nElem * DS_BA_BPW);
   Copy(&src);
}

/*************************************************************
* dsBIT_ARRAY::operator= ()
*
*************************************************************/
dsBIT_ARRAY& dsBIT_ARRAY::operator=(const dsBIT_ARRAY &src)
{
   if(&src == this) {
      return *this;
   }

   Init(src.nElem * DS_BA_BPW);
   Copy(&src);
   return *this;
}

/*************************************************************
* dsBIT_ARRAY::Init ()
*
*************************************************************/
BOOL dsBIT_ARRAY::Init  (int _nElem) 
{ 
   return Resize(_nElem);
}

/*************************************************************
* dsBIT_ARRAY::Clear ()
*
*************************************************************/
void dsBIT_ARRAY::Clear ()
{
   if (nElem == 0) {
      return;
   }

   memset(array, 0, (nElem+1) * sizeof(int)); 

   return ;
}


/*************************************************************
* dsBIT_ARRAY::Term ()
*
*************************************************************/
void dsBIT_ARRAY::Term (void)
{
   free(array); 
   array = NULL; 
   nElem = 0; 

   return ;
}

/*************************************************************
* dsBIT_ARRAY::Resize ()
* ATTENTION: it's better to clear array after downsizing it
*************************************************************/
BOOL dsBIT_ARRAY::Resize  (int _nElem) 
{ 
   ASSERT(sizeof(int) == 4);
   int oldElem = nElem;
   nElem = dsBIT_ARRAY_IMPL::Bit2Idx(_nElem + (DS_BA_BPW-1));
   if ((array = (DWORD*)realloc(array, (nElem+1) * sizeof(DWORD))) == NULL) {
      return FALSE;
   }
   int diff = nElem - oldElem;
   if (diff > 0) {
      // clear new elements
      memset(array + oldElem, 0, sizeof(DWORD) * diff);
   } 
   return TRUE;
}



/*************************************************************
* dsBIT_ARRAY::SetYesArr ()
*************************************************************/
void dsBIT_ARRAY::SetYesArr (int i, dsBIT_ARRAY *arr) 
{
   int   ind, shift;

   ind   = dsBIT_ARRAY_IMPL::Bit2Idx(i);
   shift = dsBIT_ARRAY_IMPL::Bit2Shift(i);

   if (shift == 0) {
      for (i = 0; i < arr->nElem; i ++) {
         _SetStateYes(array[ind+i+0], arr->array[i]);
      }
   } else {
      for (i = 0; i < arr->nElem; i ++) {
         _SetStateYes(array[ind+i+0], arr->array[i] << shift);
         _SetStateYes(array[ind+i+1], (arr->array[i] >> (DS_BA_BPW-shift)));
      }
   }
   return;
}
/*************************************************************
* dsBIT_ARRAY::SetNoArr ()
*************************************************************/
void dsBIT_ARRAY::SetNoArr (int i, dsBIT_ARRAY *arr) 
{
   int   ind, shift;

   ind   = dsBIT_ARRAY_IMPL::Bit2Idx(i);
   shift = dsBIT_ARRAY_IMPL::Bit2Shift(i);

   if (shift == 0) {
      for (i = 0; i < arr->nElem; i ++) {
         _SetStateNo(array[ind+i+0], arr->array[i]);
      }
   } else {
      for (i = 0; i < arr->nElem; i ++) {
         _SetStateNo(array[ind+i+0], arr->array[i] << shift);
         _SetStateNo(array[ind+i+1], arr->array[i] >> (DS_BA_BPW-shift));
      }
   }
   return;
}
/*************************************************************
* dsBIT_ARRAY::IsArr ()
*************************************************************/
BOOL dsBIT_ARRAY::IsArr (int i, dsBIT_ARRAY *arr) 
{
   int   ind, shift;

   ind   = dsBIT_ARRAY_IMPL::Bit2Idx(i);
   shift = dsBIT_ARRAY_IMPL::Bit2Shift(i);

   if (shift == 0) {
      for (i = 0; i < arr->nElem; i ++) {
         if (_IsState(array[ind+i], arr->array[i])) {
            return TRUE;
         }
      }
   } else {
      for (i = 0; i < arr->nElem; i ++) {
         if (_IsState(array[ind+i], arr->array[i] << shift)) {
            return TRUE;
         }
         if (_IsState(array[ind+i+1], arr->array[i] >> (DS_BA_BPW-shift))) {
            return TRUE;
         }
      }
   }
   return FALSE;
}

/*************************************************************
* dsBIT_ARRAY::Copy ()
*************************************************************/
void  dsBIT_ARRAY::Copy (const dsBIT_ARRAY *pSrc)
{
   ASSERT(nElem == pSrc->nElem);
   memcpy(array, pSrc->array, nElem * sizeof(DWORD));

   return;
}

/**************************************************************************
* dsBIT_ARRAY::Compare()                                                  *
*                                                                         *
**************************************************************************/
int dsBIT_ARRAY::Compare(const dsBIT_ARRAY & p) const
{
   const int len = min(GetElemCount(), p.GetElemCount());
   
   for (int i=0; i<len; ++i) {
      if (GetElemAt(i) != p.GetElemAt(i)) {
         return ds::CMP::cmp(GetElemAt(i), p.GetElemAt(i));
      }
   }

   return GetElemCount() - p.GetElemCount();
}

//
// End-of-file DS_BIT_ARRAY.CPP
//
